//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#if _MSC_VER > 1000
#pragma once
#endif

#ifndef __EZSTRBUF_H__
#define __EZSTRBUF_H__

#include <elstring.h>

typedef enum
{
    NumberFormat_RightAlign              = 0x00000000,
    NumberFormat_LeftAlign               = 0x00010000,
    NumberFormat_Signed                  = 0x00020000,
    NumberFormat_ZeroPrefixed            = 0x00040000,
    NumberFormat_BlankPrefixed           = 0x00080000,
    NumberFormat_PoundSign               = 0x00100000,
    NumberFormat_PrefixMask              = 0x00FF0000,

    NumberFormat_Decimal                 = 0x00000000,
    NumberFormat_UsignedDecimal          = 0x01000000,
    NumberFormat_Octal                   = 0x02000000,
    NumberFormat_Hex                     = 0x04000000,
    NumberFormat_BigHex                  = 0x08000000,
    NumberFormat_IntegerMask             = 0x0F000000,

    NumberFormat_Double                  = 0x00000000,
    NumberFormat_ScientificDouble        = 0x10000000,
    NumberFormat_BigScientificDouble     = 0x20000000,
    NumberFormat_FlexScientificDouble    = 0x40000000,
    NumberFormat_BigFlexScientificDouble = 0x80000000,
    NumberFormat_DoubleMask              = 0xF0000000,

    NumberFormat_TypeMask                = 0xFF000000,

    NumberFormat_Mask                    = 0xFFFF0000,
} _NumberFormat;

//
// Memory structure of WStringBuf/AStringBuf:
//          __________
//         |  pBuf    |
//         |          v
//  +------------+    +-----------------------+
//  | CarQuintet | ---| wchar_t/char's Buffer |
//  +------------+    +-----------------------+
//  ^
//  |____ WStringBuf/AStringBuf (m_pbuf)
//

#ifdef __cplusplus
extern "C" {
#endif
    _ELASTOS PCarQuintet __cdecl _WStringBuf_Init(_ELASTOS PVoid pv,
        _ELASTOS Int32 length, _ELASTOS Boolean bHeapAlloced);
    _ELASTOS PCarQuintet __cdecl _AStringBuf_Init(_ELASTOS PVoid pv,
        _ELASTOS Int32 length, _ELASTOS Boolean bHeapAlloced);
    _ELASTOS PCarQuintet __cdecl _AStringBuf_Alloc(_ELASTOS Int32 length);
    _ELASTOS PCarQuintet __cdecl _WStringBuf_Alloc(_ELASTOS Int32 length);
    _ELASTOS PCarQuintet __cdecl _AStringBuf_Alloc_Box(char *pstr,
        _ELASTOS Int32 size);
    _ELASTOS PCarQuintet __cdecl _WStringBuf_Alloc_Box(wchar_t *pwstr,
        _ELASTOS Int32 size);

    _ELASTOS Int32 __cdecl _WStringBuf_EstimateAStringLength(
        const _ELASTOS PCarQuintet pCq, _ELASTOS Encoding encoding);
    _ELASTOS Int32 __cdecl _AStringBuf_EstimateWStringLength(
        const _ELASTOS PCarQuintet pCq, _ELASTOS Encoding encoding);

    _ELASTOS Int32 __cdecl _WStringBuf_ToInt32(const _ELASTOS PCarQuintet pCq);
    _ELASTOS Int32 __cdecl _AStringBuf_ToInt32(const _ELASTOS PCarQuintet pCq);
    _ELASTOS Int64 __cdecl _WStringBuf_ToInt64(const _ELASTOS PCarQuintet pCq);
    _ELASTOS Int64 __cdecl _AStringBuf_ToInt64(const _ELASTOS PCarQuintet pCq);
    _ELASTOS Boolean __cdecl _WStringBuf_ToBoolean(const _ELASTOS PCarQuintet pCq);
    _ELASTOS Boolean __cdecl _AStringBuf_ToBoolean(const _ELASTOS PCarQuintet pCq);
    _ELASTOS Double __cdecl _WStringBuf_ToDouble(const _ELASTOS PCarQuintet pCq);
    _ELASTOS Double __cdecl _AStringBuf_ToDouble(const _ELASTOS PCarQuintet pCq);

    _ELASTOS Int32 __cdecl _WStringBuf_GetCharCount(_ELASTOS PCarQuintet pCq);
    _ELASTOS Int32 __cdecl _AStringBuf_GetCharCount(_ELASTOS PCarQuintet pCq,
        _ELASTOS Encoding encoding);
    _ELASTOS Int32 __cdecl _WStringBuf_SetLength(_ELASTOS PCarQuintet pCq,
        _ELASTOS Int32 len);
    _ELASTOS Int32 __cdecl _AStringBuf_SetLength(_ELASTOS PCarQuintet pCq,
        _ELASTOS Int32 len);
    _ELASTOS Char32 __cdecl _WStringBuf_GetChar(_ELASTOS PCarQuintet pCq,
        _ELASTOS Int32 index);
    _ELASTOS Char32 __cdecl _AStringBuf_GetChar(_ELASTOS PCarQuintet pCq,
        _ELASTOS Int32 index, _ELASTOS Encoding encoding);

    _ELASTOS Int32 __cdecl _WStringBuf_Insert(_ELASTOS PCarQuintet pCq,
        _ELASTOS Int32 offset, _ELASTOS WString ws);
    _ELASTOS Int32 __cdecl _AStringBuf_Insert(_ELASTOS PCarQuintet pCq,
        _ELASTOS Int32 offset, _ELASTOS AString as);
    _ELASTOS Int32 __cdecl _WStringBuf_Copy(_ELASTOS PCarQuintet pCq,
        _ELASTOS WString ws);
    _ELASTOS Int32 __cdecl _AStringBuf_Copy(_ELASTOS PCarQuintet pCq,
        _ELASTOS AString as);
    _ELASTOS Int32 __cdecl _WStringBuf_Replace(_ELASTOS PCarQuintet pCq,
        _ELASTOS Int32 index, _ELASTOS Int32 count, _ELASTOS WString ws);
    _ELASTOS Int32 __cdecl _AStringBuf_Replace(_ELASTOS PCarQuintet pCq,
        _ELASTOS Int32 index, _ELASTOS Int32 count, _ELASTOS AString as);

    _ELASTOS Int32 __cdecl _WStringBuf_Append_WString(
        _ELASTOS PCarQuintet pCq, _ELASTOS WString ws, _ELASTOS Int32 offset,
        _ELASTOS Int32 count);
    _ELASTOS Int32 __cdecl _AStringBuf_Append_AString(_ELASTOS PCarQuintet pCq,
        _ELASTOS AString as, _ELASTOS Int32 offset, _ELASTOS Int32 count);
    _ELASTOS Int32 __cdecl _WStringBuf_Append_WChar(_ELASTOS PCarQuintet pCq,
        _ELASTOS WChar wc);
    _ELASTOS Int32 __cdecl _AStringBuf_Append_WChar(_ELASTOS PCarQuintet pCq,
        _ELASTOS WChar wc, _ELASTOS Encoding encoding);
    _ELASTOS Int32 __cdecl _WStringBuf_Append_AChar(_ELASTOS PCarQuintet pCq,
        _ELASTOS AChar ac);
    _ELASTOS Int32 __cdecl _AStringBuf_Append_AChar(_ELASTOS PCarQuintet pCq,
        _ELASTOS AChar ch);

    _ELASTOS Int32 __cdecl _WStringBuf_Append_Int8(_ELASTOS PCarQuintet pCq,
        _ELASTOS Int8 value, _ELASTOS Flags32 fmt);
    _ELASTOS Int32 __cdecl _AStringBuf_Append_Int8(_ELASTOS PCarQuintet pCq,
        _ELASTOS Int8 value, _ELASTOS Flags32 fmt);
    _ELASTOS Int32 __cdecl _WStringBuf_Append_Int16(_ELASTOS PCarQuintet pCq,
        _ELASTOS Int16 value, _ELASTOS Flags32 fmt);
    _ELASTOS Int32 __cdecl _AStringBuf_Append_Int16(_ELASTOS PCarQuintet pCq,
        _ELASTOS Int16 value, _ELASTOS Flags32 fmt);
    _ELASTOS Int32 __cdecl _WStringBuf_Append_Int32(_ELASTOS PCarQuintet pCq,
        _ELASTOS Int32 value, _ELASTOS Flags32 fmt);
    _ELASTOS Int32 __cdecl _AStringBuf_Append_Int32(_ELASTOS PCarQuintet pCq,
        _ELASTOS Int32 value, _ELASTOS Flags32 fmt);
    _ELASTOS Int32 __cdecl _WStringBuf_Append_Int64(_ELASTOS PCarQuintet pCq,
        _ELASTOS Int64 value, _ELASTOS Flags32 fmt);
    _ELASTOS Int32 __cdecl _AStringBuf_Append_Int64(_ELASTOS PCarQuintet pCq,
        _ELASTOS Int64 value, _ELASTOS Flags32 fmt);
    _ELASTOS Int32 __cdecl _WStringBuf_Append_Double(_ELASTOS PCarQuintet pCq,
        _ELASTOS Double value, _ELASTOS Flags32 fmt);
    _ELASTOS Int32 __cdecl _AStringBuf_Append_Double(_ELASTOS PCarQuintet pCq,
        _ELASTOS Double value, _ELASTOS Flags32 fmt);
    _ELASTOS Int32 __cdecl _WStringBuf_Append_AString(_ELASTOS PCarQuintet pCq,
        _ELASTOS AString as,  _ELASTOS Int32 len, _ELASTOS Encoding encoding);
    _ELASTOS Int32 __cdecl _AStringBuf_Append_WString(_ELASTOS PCarQuintet pCq,
        _ELASTOS WString ws, _ELASTOS Int32 len, _ELASTOS Encoding encoding);

    _ELASTOS PCarQuintet __cdecl _WStringBuf_Append_DateTime(_ELASTOS PCarQuintet pCq,
        const wchar_t *fmt, _ELASTOS PDateTime pDateTime);
    _ELASTOS PCarQuintet __cdecl _AStringBuf_Append_DateTime(_ELASTOS PCarQuintet pCq,
        const char *fmt, const _ELASTOS PDateTime pDateTime);

    _ELASTOS PCarQuintet  __cdecl _WStringBuf_Box_Init(_ELASTOS PCarQuintet pCq,
        wchar_t *wstr, _ELASTOS Int32 size, _ELASTOS Boolean bHeapAlloced);
    _ELASTOS PCarQuintet  __cdecl _AStringBuf_Box_Init(_ELASTOS PCarQuintet pCq,
        char *str, _ELASTOS Int32 size, _ELASTOS Boolean bHeapAlloced);

    //--------
    _ELASTOS Boolean __cdecl _AStringBuf_Contains(const _ELASTOS PCarQuintet pCq,
        const char *substr, _ELASTOS StringCase stringCase,
        _ELASTOS Encoding encoding);
    _ELASTOS Boolean __cdecl _WStringBuf_Contains(const _ELASTOS PCarQuintet pCq,
        const wchar_t *substr, _ELASTOS StringCase stringCase);

    _ELASTOS Boolean __cdecl _AStringBuf_StartWith(const _ELASTOS PCarQuintet pCq,
        const char *substr, _ELASTOS StringCase stringCase,
        _ELASTOS Encoding encoding);
    _ELASTOS Boolean __cdecl _WStringBuf_StartWith(const _ELASTOS PCarQuintet pCq,
        const wchar_t *substr, _ELASTOS StringCase stringCase);
    _ELASTOS Boolean __cdecl _AStringBuf_EndWith(const _ELASTOS PCarQuintet pCq,
        const char *substr, _ELASTOS StringCase stringCase,
        _ELASTOS Encoding encoding);
    _ELASTOS Boolean __cdecl _WStringBuf_EndWith(const _ELASTOS PCarQuintet pCq,
        const wchar_t *substr, _ELASTOS StringCase stringCase);

    _ELASTOS Int32 __cdecl _AStringBuf_IndexOf_AChar(const _ELASTOS PCarQuintet pCq, char ch,
        _ELASTOS StringCase stringCase);
    _ELASTOS Int32 __cdecl _AStringBuf_IndexOf_AnyAChar(const _ELASTOS PCarQuintet pCq,
        const char* strCharSet, _ELASTOS StringCase stringCase);
    _ELASTOS Int32 __cdecl _AStringBuf_IndexOf_Char(const _ELASTOS PCarQuintet pCq,
        _ELASTOS Char32 ch, _ELASTOS StringCase stringCase,
        _ELASTOS Encoding encoding);
    _ELASTOS Int32 __cdecl _AStringBuf_IndexOf_AnyChar(const _ELASTOS PCarQuintet pCq,
        _ELASTOS Char32 *strCharSet, _ELASTOS StringCase stringCase,
        _ELASTOS Encoding encoding);
    _ELASTOS Int32 __cdecl _AStringBuf_IndexOf_Substring(const _ELASTOS PCarQuintet pCq,
        const char *substr, _ELASTOS StringCase stringCase,
        _ELASTOS Encoding encoding);
    _ELASTOS Int32 __cdecl _WStringBuf_IndexOf_WChar(const _ELASTOS PCarQuintet pCq,
        wchar_t ch, _ELASTOS StringCase stringCase);
    _ELASTOS Int32 __cdecl _WStringBuf_IndexOf_AnyWChar(const _ELASTOS PCarQuintet pCq,
        const wchar_t* strCharSet, _ELASTOS StringCase stringCase);
    _ELASTOS Int32 __cdecl _WStringBuf_IndexOf_Char(const _ELASTOS PCarQuintet pCq,
        _ELASTOS Char32 ch, _ELASTOS StringCase stringCase);
    _ELASTOS Int32 __cdecl _WStringBuf_IndexOf_AnyChar(const _ELASTOS PCarQuintet pCq,
        _ELASTOS Char32 *strCharSet, _ELASTOS StringCase stringCase);
    _ELASTOS Int32 __cdecl _WStringBuf_IndexOf_Substring(const _ELASTOS PCarQuintet pCq,
        const wchar_t *substr, _ELASTOS StringCase stringCase);

    _ELASTOS Int32 __cdecl _AStringBuf_LastIndexOf_AChar(const _ELASTOS PCarQuintet pCq, char ch,
        _ELASTOS StringCase stringCase);
    _ELASTOS Int32 __cdecl _AStringBuf_LastIndexOf_AnyAChar(const _ELASTOS PCarQuintet pCq,
        const char* strCharSet, _ELASTOS StringCase stringCase);
    _ELASTOS Int32 __cdecl _AStringBuf_LastIndexOf_Char(const _ELASTOS PCarQuintet pCq,
        _ELASTOS Char32 ch, _ELASTOS StringCase stringCase,
        _ELASTOS Encoding encoding);
    _ELASTOS Int32 __cdecl _AStringBuf_LastIndexOf_AnyChar(const _ELASTOS PCarQuintet pCq,
        _ELASTOS Char32 *strCharSet, _ELASTOS StringCase stringCase,
        _ELASTOS Encoding encoding);
    _ELASTOS Int32 __cdecl _AStringBuf_LastIndexOf_Substring(const _ELASTOS PCarQuintet pCq,
        const char *substr, _ELASTOS StringCase stringCase,
        _ELASTOS Encoding encoding);
    _ELASTOS Int32 __cdecl _WStringBuf_LastIndexOf_WChar(const _ELASTOS PCarQuintet pCq,
        wchar_t ch, _ELASTOS StringCase stringCase);
    _ELASTOS Int32 __cdecl _WStringBuf_LastIndexOf_AnyWChar(const _ELASTOS PCarQuintet pCq,
        const wchar_t *strCharSet, _ELASTOS StringCase stringCase);
    _ELASTOS Int32 __cdecl _WStringBuf_LastIndexOf_Char(const _ELASTOS PCarQuintet pCq,
        _ELASTOS Char32 ch, _ELASTOS StringCase stringCase);
    _ELASTOS Int32 __cdecl _WStringBuf_LastIndexOf_AnyChar(const _ELASTOS PCarQuintet pCq,
        _ELASTOS Char32 *strCharSet, _ELASTOS StringCase stringCase);
    _ELASTOS Int32 __cdecl _WStringBuf_LastIndexOf_Substring(const _ELASTOS PCarQuintet pCq,
        const wchar_t *substr, _ELASTOS StringCase stringCase);

    char* __cdecl _AStringBuf_Substring(const _ELASTOS PCarQuintet pCq, _ELASTOS Int32 start,
        _ELASTOS PCarQuintet sub, _ELASTOS Encoding encoding);
    char* __cdecl _AStringBuf_Substring_Length(const _ELASTOS PCarQuintet pCq, _ELASTOS Int32 start,
    	_ELASTOS Int32 len, _ELASTOS PCarQuintet sub, _ELASTOS Encoding encoding);
    wchar_t* __cdecl _WStringBuf_Substring(const _ELASTOS PCarQuintet pCq,
        _ELASTOS Int32 start, _ELASTOS PCarQuintet sub);
    wchar_t* __cdecl _WStringBuf_Substring_Length(const _ELASTOS PCarQuintet pCq,
        _ELASTOS Int32 start, _ELASTOS Int32 len, _ELASTOS PCarQuintet sub);

    _ELASTOS PCarQuintet __cdecl _AStringBuf_ToLowerCase(_ELASTOS PCarQuintet pCq,
        _ELASTOS Encoding encoding);
    _ELASTOS PCarQuintet __cdecl _WStringBuf_ToLowerCase(_ELASTOS PCarQuintet pCq);
    _ELASTOS PCarQuintet __cdecl _AStringBuf_ToUpperCase(_ELASTOS PCarQuintet pCq,
        _ELASTOS Encoding encoding);
    _ELASTOS PCarQuintet __cdecl _WStringBuf_ToUpperCase(_ELASTOS PCarQuintet pCq);

    _ELASTOS PCarQuintet __cdecl _AStringBuf_TrimStart(_ELASTOS PCarQuintet pCq);
    _ELASTOS PCarQuintet __cdecl _WStringBuf_TrimStart(_ELASTOS PCarQuintet pCq);
    _ELASTOS PCarQuintet __cdecl _AStringBuf_TrimEnd(_ELASTOS PCarQuintet pCq);
    _ELASTOS PCarQuintet __cdecl _WStringBuf_TrimEnd(_ELASTOS PCarQuintet pCq);
    _ELASTOS PCarQuintet __cdecl _AStringBuf_Trim(_ELASTOS PCarQuintet pCq);
    _ELASTOS PCarQuintet __cdecl _WStringBuf_Trim(_ELASTOS PCarQuintet pCq);

    _ELASTOS PCarQuintet __cdecl _AStringBuf_PadLeft(_ELASTOS PCarQuintet pCq,
        _ELASTOS Int32 width);
    _ELASTOS PCarQuintet __cdecl _WStringBuf_PadLeft(_ELASTOS PCarQuintet pCq,
        _ELASTOS Int32 width);
    _ELASTOS PCarQuintet __cdecl _AStringBuf_PadLeft_AChar(
        _ELASTOS PCarQuintet pCq, _ELASTOS Int32 width, _ELASTOS AChar ch);
    _ELASTOS PCarQuintet __cdecl _WStringBuf_PadLeft_WChar(
        _ELASTOS PCarQuintet pCq, _ELASTOS Int32 width, _ELASTOS WChar ch);

    _ELASTOS PCarQuintet __cdecl _AStringBuf_PadRight(_ELASTOS PCarQuintet pCq,
        _ELASTOS Int32 width);
    _ELASTOS PCarQuintet __cdecl _WStringBuf_PadRight(_ELASTOS PCarQuintet pCq,
        _ELASTOS Int32 width);
    _ELASTOS PCarQuintet __cdecl _AStringBuf_PadRight_AChar(
        _ELASTOS PCarQuintet pCq, _ELASTOS Int32 width, _ELASTOS AChar ch);
    _ELASTOS PCarQuintet __cdecl _WStringBuf_PadRight_WChar(
        _ELASTOS PCarQuintet pCq, _ELASTOS Int32 width, _ELASTOS WChar ch);

    _ELASTOS PCarQuintet __cdecl _AStringBuf_EncodeURL(_ELASTOS PCarQuintet pCq,
        _ELASTOS WString ws, _ELASTOS Encoding encoding);
    _ELASTOS PCarQuintet __cdecl _WStringBuf_DecodeURL(_ELASTOS PCarQuintet pCq,
        _ELASTOS AString as, _ELASTOS Encoding encoding);

#ifdef __cplusplus
}
#endif

#ifdef __cplusplus

_ELASTOS_NAMESPACE_BEGIN

INLINE _ELASTOS Flags32 MakeNumberFormat(_ELASTOS Flags32 fmt,
        _ELASTOS Int32 width = 0, _ELASTOS Int32 precision = 0)
{
    return ((fmt & 0xFFFF0000) | (width & 0xFF) | ((precision  <<  8) & 0xFF00));
}

class WStringBuf : public CarQuintet
{
public:
    wchar_t *GetPayload() const {
        return (wchar_t *)m_pBuf;
    }

    Int32 GetCapacity() const {
        if (!m_pBuf || m_size < (Int32)sizeof(WChar)) return 0;
        else return m_size / sizeof(WChar) - 1;
    }

    Int32 GetAvailableSpace() const {
        return (m_size - m_used) / sizeof(WChar);
    }

    Int32 GetLength() const{
        if (m_used < (Int32)sizeof(WChar)) return 0;
        else return m_used / sizeof(WChar) - 1;
    }

    Int32 EstimateAStringLength(Encoding encoding = Encoding_Default) const {
        return _WStringBuf_EstimateAStringLength((const PCarQuintet)this, encoding);
    }

    Int32 SetLength(Int32 len) const {
        return _WStringBuf_SetLength((const PCarQuintet)this, len);
    }

    Int32 ToInt32() const {
        return _WStringBuf_ToInt32((const PCarQuintet)this);
    }

    Int64 ToInt64() const {
        return _WStringBuf_ToInt64((const PCarQuintet)this);
    }

    Boolean ToBoolean() const {
        return _WStringBuf_ToBoolean((const PCarQuintet)this);
    }

    Double ToDouble() const {
        return _WStringBuf_ToDouble((const PCarQuintet)this);
    }

    Int32 GetCharCount() const{
        if (m_used < (Int32)sizeof(WChar)) return 0;
        return _WStringBuf_GetCharCount((PCarQuintet)this);
    }

    Char32 GetChar(Int32 index) const {
        if (m_used < (Int32)sizeof(WChar)) return 0xFFFFFFFF;
        return _WStringBuf_GetChar((PCarQuintet)this, index);
    }

    //---- Contains ----
    Boolean Contains(const WString& substr,
            StringCase stringCase = StringCase_Sensitive) const {
        return _WStringBuf_Contains((const PCarQuintet)this, substr, stringCase);
    }

    Boolean StartWith(const WString& substr,
            StringCase stringCase = StringCase_Sensitive) const {
        return _WStringBuf_StartWith((const PCarQuintet)this, substr, stringCase);
    }

    Boolean EndWith(const WString& substr,
            StringCase stringCase = StringCase_Sensitive) const {
        return _WStringBuf_EndWith((const PCarQuintet)this, substr, stringCase);
    }

    //---- IndexOf ----
    Int32 IndexOf(WChar ch,  StringCase stringCase = StringCase_Sensitive) const {
        return _WStringBuf_IndexOf_WChar((const PCarQuintet)this, ch, stringCase);
    }

    Int32 IndexOfAny(const WString& strCharSet,
            StringCase stringCase  = StringCase_Sensitive) const {
        return _WStringBuf_IndexOf_AnyWChar((const PCarQuintet)this, strCharSet, stringCase);
    }

    Int32 IndexOfChar(Char32 ch,
            StringCase stringCase = StringCase_Sensitive) const {
        return _WStringBuf_IndexOf_Char((const PCarQuintet)this, ch, stringCase);
    }

    Int32 IndexOfAnyChar(Char32 *strCharSet,
            StringCase stringCase = StringCase_Sensitive) const {
        return _WStringBuf_IndexOf_AnyChar((const PCarQuintet)this, strCharSet, stringCase);
    }

    Int32 IndexOf(const WString& str,
            StringCase stringCase  = StringCase_Sensitive) const {
        return _WStringBuf_IndexOf_Substring((const PCarQuintet)this, str, stringCase);
    }

    //---- LastIndexOf ----
    Int32 LastIndexOf(WChar ch,
            StringCase stringCase = StringCase_Sensitive) const {
        return _WStringBuf_LastIndexOf_WChar((const PCarQuintet)this, ch, stringCase);
    }

    Int32 LastIndexOfAny(const WString& strCharSet,
            StringCase stringCase  = StringCase_Sensitive) const {
        return _WStringBuf_LastIndexOf_AnyWChar((const PCarQuintet)this, strCharSet, stringCase);
    }

    Int32 LastIndexOfChar(Char32 ch,
            StringCase stringCase = StringCase_Sensitive) const {
        return _WStringBuf_LastIndexOf_Char((const PCarQuintet)this, ch, stringCase);
    }

    Int32 LastIndexOfAnyChar(Char32 *strCharSet,
            StringCase stringCase = StringCase_Sensitive) const {
        return _WStringBuf_LastIndexOf_AnyChar((const PCarQuintet)this, strCharSet, stringCase);
    }

    Int32 LastIndexOf(const WString& str,
            StringCase stringCase  = StringCase_Sensitive) const {
        return _WStringBuf_LastIndexOf_Substring((const PCarQuintet)this, str, stringCase);
    }

    //---- Substring ----
    WString Substring(Int32 start, WStringBuf& sub) {
        return _WStringBuf_Substring((const PCarQuintet)this, start, (PCarQuintet)&sub);
    }

    WString Substring(Int32 start, Int32 len, WStringBuf& sub) {
        return _WStringBuf_Substring_Length((const PCarQuintet)this, start, len, (PCarQuintet)&sub);
    }

    //---- ToLowerCase ----
    WStringBuf& ToLowerCase() {
        _WStringBuf_ToLowerCase((PCarQuintet)this);
        return *this;
    }

    //---- ToUpperCase ----
    WStringBuf& ToUpperCase() {
        _WStringBuf_ToUpperCase((PCarQuintet)this);
        return *this;
    }

    //---- TrimStart ----
    WStringBuf& TrimStart() {
        _WStringBuf_TrimStart((PCarQuintet)this);
        return *this;
    }

    //---- TrimEnd ----
    WStringBuf& TrimEnd() {
        _WStringBuf_TrimEnd((PCarQuintet)this);
        return *this;
    }

    //---- Trim ----
    WStringBuf& Trim() {
        _WStringBuf_Trim((PCarQuintet)this);
        return *this;
    }

///
    WStringBuf& PadLeft(Int32 width) {
        _WStringBuf_PadLeft((PCarQuintet)this, width);
        return *this;
    }

    WStringBuf& PadLeft(Int32 width, WChar ch) {
        _WStringBuf_PadLeft_WChar((PCarQuintet)this, width, ch);
        return *this;
    }

    WStringBuf& PadRight(Int32 width) {
        _WStringBuf_PadRight((PCarQuintet)this, width);
        return *this;
    }

    WStringBuf& PadRight(Int32 width, WChar ch) {
        _WStringBuf_PadRight_WChar((PCarQuintet)this, width, ch);
        return *this;
    }

    operator PCarQuintet() {
        return this;
    }

    operator wchar_t*() const {
        return (wchar_t *)m_pBuf;
    }

    operator WString() const {
        return (wchar_t *)m_pBuf;
    }

    Boolean IsNull() const {
        return m_pBuf == NULL;
    }

    Boolean IsEmpty() const {
        assert(m_pBuf);
        return (m_used == sizeof(WChar)) && (*(WChar *)m_pBuf == L'\0');
    }

    Boolean IsNullOrEmpty() const {
        return (m_pBuf == NULL)
                || ((m_used == sizeof(WChar)) && (*(WChar *)m_pBuf == L'\0'));
    }

    void SetEmpty() {
        assert(m_pBuf);
        m_used = sizeof(WChar);
        *(WChar *)m_pBuf = L'\0';
    }

    WStringBuf& Insert(Int32 offset, const WString& ws) {
        _WStringBuf_Insert(this, offset, ws);
        return *this;
    }

    WStringBuf& Append(const WString& ws) {
        return Insert(GetLength(), ws);
    }

    WStringBuf& Append(const WString& ws, Int32 offset, Int32 n) {
        _WStringBuf_Append_WString(this, ws, offset, n);
        return *this;
    }

    WStringBuf& Append(const AString& as, Encoding encoding = Encoding_Default) {
        _WStringBuf_Append_AString(this, as, -1, encoding);
        return *this;
    }

    WStringBuf& Append(const AString& as, Int32 len, Encoding encoding) {
        _WStringBuf_Append_AString(this, as, len, encoding);
        return *this;
    }

    WStringBuf& Append(WChar wc) {
        _WStringBuf_Append_WChar(this, wc);
        return *this;
    }

    WStringBuf& Append(AChar ac) {
        _WStringBuf_Append_AChar(this, ac);
        return *this;
    }

    WStringBuf& Append(Boolean boolean) {
        if (boolean) {
            return Append(L"True");
        }
        else {
            return Append(L"False");
        }
    }

    WStringBuf& Append(Int8 value, Flags32 fmt = 0) {
        _WStringBuf_Append_Int8(this, value, fmt);
        return *this;
    }

    WStringBuf& Append(Int16 value, Flags32 fmt = 0) {
        _WStringBuf_Append_Int16(this, value, fmt);
        return *this;
    }

    WStringBuf& Append(Int32 value, Flags32 fmt = 0) {
        _WStringBuf_Append_Int32(this, value, fmt);
        return *this;
    }

    WStringBuf& Append(Int64 value, Flags32 fmt = 0) {
        _WStringBuf_Append_Int64(this, value, fmt);
        return *this;
    }

    WStringBuf& Append(Double value, Flags32 fmt = 0) {
        _WStringBuf_Append_Double(this, value, fmt);
        return *this;
    }

    WStringBuf& Append(const WString& fmt, const DateTime& dateTime){
        _WStringBuf_Append_DateTime(this, fmt, (PDateTime)&dateTime);
        return *this;
    }

    WStringBuf& operator<<(const WString& ws) {
        return Append(ws);
    }

    WStringBuf& operator<<(const AString& as) {
        return Append(as);
    }

    WStringBuf& operator<<(WChar wc) {
        return Append(wc);
    }

    WStringBuf& operator<<(Boolean boolean) {
        return Append(boolean);
    }

    WStringBuf& operator<<(Int8 value) {
        return Append(value);
    }

    WStringBuf& operator<<(Int16 value) {
        return Append(value);
    }

    WStringBuf& operator<<(Int32 value) {
        return Append(value);
    }

    WStringBuf& operator<<(Int64 value) {
        return Append(value);
    }

    WStringBuf& operator<<(Double value) {
        return Append(value);
    }

    WStringBuf& Replace(Int32 offset, Int32 n, const WString& ws) {
        _WStringBuf_Replace(this, offset, n, ws);
        return *this;
    }

    WStringBuf& Copy(const WString& ws) {
        if (ws.IsNull()) SetEmpty();
        _WStringBuf_Copy(this, ws);
        return *this;
    }

    WStringBuf& Copy(const AString& as, Encoding encoding = Encoding_Default) {
        SetEmpty();
        _WStringBuf_Append_AString(this, as, -1, encoding);
        return *this;
    }

    WStringBuf& Copy(const WString& ws, Int32 len) {
        SetEmpty();
        _WStringBuf_Append_WString(this, ws, 0, len);
        return *this;
    }

    // append multiple wchar_t string to WStringBuf
    WStringBuf& __cdecl Concatenate(WString firstwstr, ...);

    Int32 Compare(const WString& ws, StringCase stringCase = StringCase_Sensitive) const {
        return _WString_Compare((wchar_t *)m_pBuf, ws, stringCase);
    }

    Int32 Compare(const WStringBuf& wsb,
        StringCase stringCase = StringCase_Sensitive) const {
        return _WString_Compare((wchar_t *)m_pBuf, wsb, stringCase);
    }

    WStringBuf *Clone() const {
        return (WStringBuf *)_CarQuintet_Clone((const PCarQuintet)this);
    }

    WChar &operator[](Int32 index) {
        assert(index >= 0 && index < GetLength());
        return ((WChar*)(m_pBuf))[index];
    }

    const WChar &operator[](Int32 index) const {
        assert(index >= 0 && index < GetLength());
        return ((WChar*)(m_pBuf))[index];
    }

    static WStringBuf *Alloc(Int32 length) {
        return (WStringBuf *)_WStringBuf_Alloc(length);
    }

    static WStringBuf *Alloc(wchar_t *pwstr, Int32 size) {
        assert(pwstr);
        //on arm platform, the address of "wchar_t*" may not begin from even,
        //so we must assure it
        assert( !(((UInt32)pwstr) & 0x1) &&
            "on arm platform, assure the address begin from even");
        return (WStringBuf *)_WStringBuf_Alloc_Box(pwstr, size);
    }

    static void Free(WStringBuf *pBuf) {
        _CarQuintet_Free(pBuf);
    }

    WStringBuf(wchar_t *pwstr, Int32 size) {
        assert(pwstr && size >= 0);
        //on arm platform, the address of "wchar_t*" may not begin from even,
        //so we must assure it
        assert( !(((UInt32)pwstr) & 0x1) &&
            "on arm platform, assure the address begin from even");
        _WStringBuf_Box_Init(this, pwstr, size, FALSE);
    }

    WStringBuf& DecodeURL(const AString& as, Encoding encoding = Encoding_UTF8) {
        SetEmpty();
        _WStringBuf_DecodeURL(this, as, encoding);
        return *this;
    }

private:
    void operator = (const WStringBuf& buf) {}
    WStringBuf(const WStringBuf& buf) {}
    void* operator new(size_t) { return (void *)1; } // prohibit 'new' operator

    // prohibit comparison operator
    _ELASTOS Boolean operator<(const WStringBuf& str) const {return FALSE;} // comparisons
    _ELASTOS Boolean operator>(const WStringBuf& str) const {return FALSE;}
    _ELASTOS Boolean operator==(const WStringBuf& str) const {return FALSE;}
    _ELASTOS Boolean operator!=(const WStringBuf& str) const {return FALSE;}
    _ELASTOS Boolean operator<=(const WStringBuf& str) const {return FALSE;}
    _ELASTOS Boolean operator>=(const WStringBuf& str) const {return FALSE;}

    _ELASTOS Boolean operator<(WString str) const {return FALSE;} // comparisons WString
    _ELASTOS Boolean operator>(WString str) const {return FALSE;}
    _ELASTOS Boolean operator==(WString str) const {return FALSE;}
    _ELASTOS Boolean operator!=(WString str) const {return FALSE;}
    _ELASTOS Boolean operator<=(WString str) const {return FALSE;}
    _ELASTOS Boolean operator>=(WString str) const {return FALSE;}

    _ELASTOS Boolean operator<(wchar_t * str) const {return FALSE;} // comparisons wchar_t *
    _ELASTOS Boolean operator>(wchar_t * str) const {return FALSE;}
    _ELASTOS Boolean operator==(wchar_t * str) const {return FALSE;}
    _ELASTOS Boolean operator!=(wchar_t * str) const {return FALSE;}
    _ELASTOS Boolean operator<=(wchar_t * str) const {return FALSE;}
    _ELASTOS Boolean operator>=(wchar_t * str) const {return FALSE;}

protected:
    WStringBuf() {}
};

template<Int32 Length>
class WStringBuf_ : public WStringBuf
{
public:
    WStringBuf_()
    {
        _CarQuintet_Init(this, m_buf, (Length + 1) *  sizeof(WChar),
                        sizeof(WChar), CarQuintetFlag_Type_WChar);
#ifndef _RELEASE
        _MemoryBuf_SetByteValue(this, 0xCC);
#endif
        *(WChar *)m_pBuf = L'\0';
    }

protected:
    WChar m_buf[Length ?((Length + 1) ? (Length + 1) : (UInt32)(-1)) : sizeof(WChar)];
private:
    // prohibit "=" operator
    WStringBuf_& operator = (const WStringBuf& buf) {}
    WStringBuf_& operator = (const WStringBuf_& buf) {}
    WStringBuf_(const WStringBuf& buf) {}
    WStringBuf_(const WStringBuf_& buf) {}
};

//------------------------------------------------------------------------------

class AStringBuf : public CarQuintet
{
public:
    char *GetPayload() const
    {
        return (char *)m_pBuf;
    }

    Int32 GetCapacity() const
    {
        if (!m_pBuf || m_size < (Int32)sizeof(AChar)) return 0;
        return m_size / sizeof(AChar) - 1;
    }

    Int32 GetLength() const
    {
        if (m_used < (Int32)sizeof(AChar)) return 0;
        return m_used / sizeof(AChar) - 1;
    }

    Int32 EstimateWStringLength(Encoding encoding = Encoding_Default) const {
        return _AStringBuf_EstimateWStringLength((const PCarQuintet)this, encoding);
    }

    Int32 GetAvailableSpace() const
    {
        return (m_size - m_used) / sizeof(AChar);
    }

    Int32 SetLength(Int32 len) const
    {
        return _AStringBuf_SetLength((PCarQuintet)this, len);
    }

    Int32 ToInt32() const {
        return _AStringBuf_ToInt32((const PCarQuintet)this);
    }

    Int64 ToInt64() const {
        return _AStringBuf_ToInt64((const PCarQuintet)this);
    }

    Boolean ToBoolean() const {
        return _AStringBuf_ToBoolean((const PCarQuintet)this);
    }

    Double ToDouble() const {
        return _AStringBuf_ToDouble((const PCarQuintet)this);
    }

    Int32 GetCharCount(Encoding encoding = Encoding_Default) const
    {
        if (m_used < (Int32)sizeof(AChar)) return 0;
        return _AStringBuf_GetCharCount((PCarQuintet)this, encoding);
    }

    Char32 GetChar(Int32 index, Encoding encoding = Encoding_Default) const
    {
        if (m_used < (Int32)sizeof(AChar)) return 0xFFFFFFFF;
        return _AStringBuf_GetChar((PCarQuintet)this, index, encoding);
    }

    //---- Contains ----
    Boolean Contains(const AString& substr,
            StringCase stringCase = StringCase_Sensitive,
            Encoding encoding = Encoding_Default) const {
        return _AStringBuf_Contains((const PCarQuintet)this, substr,
            stringCase, encoding);
    }

    Boolean StartWith(const AString& substr,
            StringCase stringCase = StringCase_Sensitive,
            Encoding encoding = Encoding_Default) const {
        return _AStringBuf_StartWith((const PCarQuintet)this, substr, stringCase,
            encoding);
    }

    Boolean EndWith(const AString& substr,
            StringCase stringCase = StringCase_Sensitive,
            Encoding encoding = Encoding_Default) const {
        return _AStringBuf_EndWith((const PCarQuintet)this, substr, stringCase,
            encoding);
    }

    //---- IndexOf ----
    Int32 IndexOf(AChar ch,  StringCase stringCase = StringCase_Sensitive) const {
        return _AStringBuf_IndexOf_AChar((const PCarQuintet)this, ch, stringCase);
    }

    Int32 IndexOfAny(const AString& strCharSet,
            StringCase stringCase  = StringCase_Sensitive) const {
        return _AStringBuf_IndexOf_AnyAChar((const PCarQuintet)this, strCharSet, stringCase);
    }

    Int32 IndexOfChar(Char32 ch,
            StringCase stringCase = StringCase_Sensitive,
            Encoding encoding = Encoding_Default) const {
        return _AStringBuf_IndexOf_Char((const PCarQuintet)this, ch, stringCase,
            encoding);
    }

    Int32 IndexOfAnyChar(Char32 *strCharSet,
            StringCase stringCase = StringCase_Sensitive,
            Encoding encoding = Encoding_Default) const {
        return _AStringBuf_IndexOf_AnyChar((const PCarQuintet)this, strCharSet,
            stringCase, encoding);
    }

    Int32 IndexOf(const AString& str,
            StringCase stringCase  = StringCase_Sensitive,
            Encoding encoding = Encoding_Default) const {
        return _AStringBuf_IndexOf_Substring((const PCarQuintet)this, str,
            stringCase, encoding);
    }

    //---- LastIndexOf ----
    Int32 LastIndexOf(AChar ch,
            StringCase stringCase = StringCase_Sensitive) const {
        return _AStringBuf_LastIndexOf_AChar((const PCarQuintet)this, ch, stringCase);
    }

    Int32 LastIndexOfAny(const AString& strCharSet,
            StringCase stringCase  = StringCase_Sensitive) const {
        return _AStringBuf_LastIndexOf_AnyAChar((const PCarQuintet)this, strCharSet, stringCase);
    }

    Int32 LastIndexOfChar(Char32 ch,
            StringCase stringCase = StringCase_Sensitive,
            Encoding encoding = Encoding_Default) const {
        return _AStringBuf_LastIndexOf_Char((const PCarQuintet)this, ch, stringCase,
            encoding);
    }

    Int32 LastIndexOfAnyChar(Char32 *strCharSet,
            StringCase stringCase = StringCase_Sensitive,
            Encoding encoding = Encoding_Default) const {
        return _AStringBuf_LastIndexOf_AnyChar((const PCarQuintet)this, strCharSet,
            stringCase, encoding);
    }

    Int32 LastIndexOf(const AString& str,
            StringCase stringCase  = StringCase_Sensitive,
            Encoding encoding = Encoding_Default) const {
        return _AStringBuf_LastIndexOf_Substring((const PCarQuintet)this, str,
            stringCase, encoding);
    }

    //---- Substring ----
    AString Substring(Int32 start, AStringBuf& sub,
    		Encoding encoding = Encoding_Default) {
        return _AStringBuf_Substring((const PCarQuintet)this, start,
        	(PCarQuintet)&sub, encoding);
    }

    AString Substring(Int32 start, Int32 len, AStringBuf& sub,
    		Encoding encoding = Encoding_Default) {
        return _AStringBuf_Substring_Length((const PCarQuintet)this, start,
            len, (PCarQuintet)&sub, encoding);
    }

    //---- ToLowerCase ----
    AStringBuf& ToLowerCase(Encoding encoding = Encoding_Default) {
        _AStringBuf_ToLowerCase((PCarQuintet)this, encoding);
        return *this;
    }

    //---- ToUpperCase ----
    AStringBuf& ToUpperCase(Encoding encoding = Encoding_Default) {
        _AStringBuf_ToUpperCase((PCarQuintet)this, encoding);
        return *this;
    }

    //---- TrimStart ----
    AStringBuf& TrimStart() {
        _AStringBuf_TrimStart((PCarQuintet)this);
        return *this;
    }

    //---- TrimEnd ----
    AStringBuf& TrimEnd() {
        _AStringBuf_TrimEnd((PCarQuintet)this);
        return *this;
    }

    //---- Trim ----
    AStringBuf& Trim() {
        _AStringBuf_Trim((PCarQuintet)this);
        return *this;
    }


    //
    AStringBuf& PadLeft(Int32 width) {
        _AStringBuf_PadLeft((PCarQuintet)this, width);
        return *this;
    }

    AStringBuf& PadLeft(Int32 width, AChar ch) {
        _AStringBuf_PadLeft_AChar((PCarQuintet)this, width, ch);
        return *this;
    }

    AStringBuf& PadRight(Int32 width) {
        _AStringBuf_PadRight((PCarQuintet)this, width);
        return *this;
    }

    AStringBuf& PadRight(Int32 width, AChar ch) {
        _AStringBuf_PadRight_AChar((PCarQuintet)this, width, ch);
        return *this;
    }

    operator char*() const
    {
        return (char *)m_pBuf;
    }

    operator AString() const
    {
        return (char *)m_pBuf;
    }

    Boolean IsNull() const
    {
        return m_pBuf == NULL;
    }

    Boolean IsEmpty() const
    {
        assert(m_pBuf);
        return (m_used == sizeof(AChar)) && (*(AChar *)m_pBuf == '\0');
    }

    Boolean IsNullOrEmpty() const
    {
        return (m_pBuf == NULL)
                || (m_used == sizeof(AChar)) && (*(AChar *)m_pBuf == '\0');
    }

    void SetEmpty()
    {
        assert(m_pBuf);
        m_used = sizeof(AChar);
        *(AChar *)m_pBuf = '\0';
    }

    AStringBuf& Insert(Int32 offset, const AString& as)
    {
        _AStringBuf_Insert(this, offset, as);
        return *this;
    }

    AStringBuf& Append(const AString& as)
    {
        return Insert(GetLength(), as);
    }

    AStringBuf& Append(const AString& as, Int32 offset, Int32 count)
    {
        _AStringBuf_Append_AString(this, as, offset, count);
        return *this;
    }

    AStringBuf& Append(const WString& ws, Encoding encoding = Encoding_Default)
    {
        _AStringBuf_Append_WString(this, ws, -1, encoding);
        return *this;
    }

    AStringBuf& Append(const WString& ws, Int32 len, Encoding encoding)
    {
        _AStringBuf_Append_WString(this, ws, len, encoding);
        return *this;
    }

    AStringBuf& Append(WChar wc, Encoding encoding = Encoding_Default)
    {
        _AStringBuf_Append_WChar(this, wc, encoding);
        return *this;
    }

    AStringBuf& Append(AChar ac)
    {
        _AStringBuf_Append_AChar(this, ac);
        return *this;
    }

    AStringBuf& Append(Boolean boolean)
    {
        if (boolean) {
            return Append("True");
        }
        else {
            return Append("False");
        }
    }

    AStringBuf& Append(Int8 value, Flags32 fmt = 0)
    {
        _AStringBuf_Append_Int8(this, value, fmt);
        return *this;
    }

    AStringBuf& Append(Int16 value, Flags32 fmt = 0)
    {
        _AStringBuf_Append_Int16(this, value, fmt);
        return *this;
    }

    AStringBuf& Append(Int32 value, Flags32 fmt = 0)
    {
        _AStringBuf_Append_Int32(this, value, fmt);
        return *this;
    }

    AStringBuf& Append(Int64 value, Flags32 fmt = 0)
    {
        _AStringBuf_Append_Int64(this, value, fmt);
        return *this;
    }

    AStringBuf& Append(Double value, Flags32 fmt = 0)
    {
        _AStringBuf_Append_Double(this, value, fmt);
        return *this;
    }

    AStringBuf& Append(const AString& fmt, const DateTime& dateTime){
        _AStringBuf_Append_DateTime(this, fmt, (PDateTime)&dateTime);
        return *this;
    }

    AStringBuf& operator<<(AString as)
    {
        return Append(as);
    }

    AStringBuf& operator<<(WString ws)
    {
        return Append(ws);
    }

    AStringBuf& operator<<(AChar ac)
    {
        return Append(ac);
    }

    AStringBuf& operator<<(Boolean boolean)
    {
        return Append(boolean);
    }

    AStringBuf& operator<<(Int8 value)
    {
        return Append(value);
    }

    AStringBuf& operator<<(Int16 value)
    {
        return Append(value);
    }

    AStringBuf& operator<<(Int32 value)
    {
        return Append(value);
    }

    AStringBuf& operator<<(Int64 value)
    {
        return Append(value);
    }

    AStringBuf& operator<<(Double value)
    {
        return Append(value);
    }

    AStringBuf& Replace(Int32 offset, Int32 count, const AString& as)
    {
        _AStringBuf_Replace(this, offset, count, as);
        return *this;
    }

    AStringBuf& Copy(AString as)
    {
        if (as.IsNull()) SetEmpty();
        _AStringBuf_Copy(this, as);
        return *this;
    }

    AStringBuf& Copy(const WString& ws, Encoding encoding = Encoding_Default)
    {
        SetEmpty();
        _AStringBuf_Append_WString(this, ws, -1, encoding);
        return *this;
    }

    AStringBuf& Copy(AString as, Int32 len)
    {
        SetEmpty();
        _AStringBuf_Append_AString(this, as, 0, len);
        return *this;
    }

    // append multiple char string to AStringBuf
    AStringBuf& __cdecl Concatenate(AString firststr, ...);

    Int32 Compare(const AString& as, StringCase stringCase = StringCase_Sensitive) const {
        return _AString_Compare((char *)m_pBuf, as, stringCase);
    }

    Int32 Compare(const AStringBuf& asb,
        StringCase stringCase = StringCase_Sensitive) const {
        return _AString_Compare((char *)m_pBuf, asb, stringCase);
    }

    AStringBuf *Clone() const {
        return (AStringBuf *)_CarQuintet_Clone((const PCarQuintet)this);
    }

    AChar &operator[](Int32 index) {
        assert(index >= 0 && index < GetLength());
        return ((AChar*)m_pBuf)[index];
    }

    const AChar &operator[](Int32 index) const {
        assert(index >= 0 && index < GetLength());
        return ((AChar*)m_pBuf)[index];
    }

    static AStringBuf *Alloc(Int32 length) {
        return (AStringBuf *)_AStringBuf_Alloc(length);
    }

    static AStringBuf *Alloc(char *pstr, Int32 size) {
        assert(pstr);
        return (AStringBuf *)_AStringBuf_Alloc_Box(pstr, size);
    }

    static void Free(AStringBuf *pBuf) {
        _CarQuintet_Free(pBuf);
    }

    AStringBuf(char *pstr, Int32 size) {
        assert(pstr && size >= 0);
        _AStringBuf_Box_Init(this, pstr, size, FALSE);
    }

    AStringBuf& EncodeURL(const WString& ws, Encoding encoding = Encoding_UTF8) {
        SetEmpty();
        _AStringBuf_EncodeURL(this, ws, encoding);
        return *this;
    }

private:
    void operator = (const AStringBuf& buf) {}
    AStringBuf(const AStringBuf& buf) {}
    void* operator new(size_t) { return (void *)1; } // prohibit 'new' operator

    // prohibit comparison operator
    _ELASTOS Boolean operator<(const AStringBuf& str) const {return FALSE;} // comparisons
    _ELASTOS Boolean operator>(const AStringBuf& str) const {return FALSE;}
    _ELASTOS Boolean operator==(const AStringBuf& str) const {return FALSE;}
    _ELASTOS Boolean operator!=(const AStringBuf& str) const {return FALSE;}
    _ELASTOS Boolean operator<=(const AStringBuf& str) const {return FALSE;}
    _ELASTOS Boolean operator>=(const AStringBuf& str) const {return FALSE;}

    _ELASTOS Boolean operator<(AString str) const {return FALSE;} // comparisons AString
    _ELASTOS Boolean operator>(AString str) const {return FALSE;}
    _ELASTOS Boolean operator==(AString str) const {return FALSE;}
    _ELASTOS Boolean operator!=(AString str) const {return FALSE;}
    _ELASTOS Boolean operator<=(AString str) const {return FALSE;}
    _ELASTOS Boolean operator>=(AString str) const {return FALSE;}

    _ELASTOS Boolean operator<(char * str) const {return FALSE;} // comparisons char *
    _ELASTOS Boolean operator>(char * str) const {return FALSE;}
    _ELASTOS Boolean operator==(char * str) const {return FALSE;}
    _ELASTOS Boolean operator!=(char * str) const {return FALSE;}
    _ELASTOS Boolean operator<=(char * str) const {return FALSE;}
    _ELASTOS Boolean operator>=(char * str) const {return FALSE;}

protected:
    AStringBuf() {}
};

template<Int32 Length>
class AStringBuf_ : public AStringBuf
{
public:
    AStringBuf_()
    {
        _CarQuintet_Init(this, m_buf, (Length + 1) *  sizeof(AChar),
                        sizeof(AChar), CarQuintetFlag_Type_AChar);
#ifndef _RELEASE
        _MemoryBuf_SetByteValue(this, 0xCC);
#endif
        *(AChar *)m_pBuf = '\0';
    }

protected:
    AChar m_buf[Length ?((Length + 1) ? (Length + 1) : (UInt32)(-1)) : sizeof(AChar)];
private:
    // prohibit "=" operator
    AStringBuf_& operator = (const AStringBuf& buf) {}
    AStringBuf_& operator = (const AStringBuf_& buf) {}
    AStringBuf_(const AStringBuf& buf) {}
    AStringBuf_(const AStringBuf_& buf) {}
};

//==========================================================================
// WStringBuf INLINE functions for CPP style
//

INLINE WStringBuf& __cdecl WStringBuf::Concatenate(WString firstwstr,...)
{
    va_list argptr;
    va_start(argptr, firstwstr);

    const wchar_t* pwstr = (const wchar_t *)firstwstr;

    while (pwstr != NULL) {
        Insert(GetLength(), pwstr);
        pwstr = (wchar_t *)va_arg(argptr, const wchar_t*);
    }

    va_end(argptr);

    return *this;
}

//==========================================================================
// AStringBuf INLINE functions for CPP style
//

INLINE AStringBuf& __cdecl AStringBuf::Concatenate(AString firststr,...)
{
    va_list argptr;
    va_start(argptr, firststr);

    const char* pstr = (const char *)firststr;
    while (pstr != NULL) {
        Insert(GetLength(), pstr);
        pstr = va_arg(argptr, const char*);
    }
    va_end(argptr);

    return *this;
}

typedef WStringBuf*                 PWStringBuf;
typedef AStringBuf*                 PAStringBuf;

#define NULL_WSTRINGBUF  \
            *(const WStringBuf *)_CarQuintet_GetNullValue( \
            CarQuintetFlag_Type_WChar)

#define NULL_ASTRINGBUF \
            *(const AStringBuf *)_CarQuintet_GetNullValue( \
            CarQuintetFlag_Type_AChar)

_ELASTOS_NAMESPACE_END

#else //!__cplusplus

typedef CarQuintet WStringBuf;
typedef CarQuintet AStringBuf;

#define NULL_WSTRINGBUF 0
#define NULL_ASTRINGBUF 0

INLINE WString _WStringBufToWString(WStringBuf wStrBuf)
{
    assert(&wStrBuf
        && "Can't convert a null WStringBuf object to WString type!");
    return (WString)wStrBuf.m_pBuf;
}

//AStringBuf
#define ASTRINGBUF_BOX(pCq, pBuf, size, used) \
            do { \
                assert((size) >= 0 && (used) >= 0); \
                (pCq)->m_flags = CarQuintetFlag_Type_AChar; \
                (pCq)->m_reserve = 0; \
                (pCq)->m_size = size + 1; \
                (pCq)->m_used = used + 1; \
                (pCq)->m_pBuf = pBuf; \
            } while (0)

#define ASTRINGBUF_UNBOX(Cq, ppBuf, pSize, pUsed) \
            do { \
                (*ppBuf) = (Cq).m_pBuf; \
                *(Int32*)pSize= (Cq).m_size / sizeof(char) - 1; \
                *(Int32*)pUsed = (Cq).m_used / sizeof(char) - 1; \
            } while (0)

//WStringBuf
#define WSTRINGBUF_BOX(pCq, pBuf, size, used) \
            do { \
                assert((size) >= 0 && (used) >= 0); \
                (pCq)->m_flags = CarQuintetFlag_Type_WChar; \
                (pCq)->m_reserve = 0; \
                (pCq)->m_size = (size + 1) * sizeof(wchar_t); \
                (pCq)->m_used = (used + 1) * sizeof(wchar_t); \
                (pCq)->m_pBuf = pBuf; \
            } while (0)

#define WSTRINGBUF_UNBOX(Cq, ppBuf, pSize, pUsed) \
            do { \
                (*ppBuf) = (Cq).m_pBuf; \
                *(Int32*)pSize= (Cq).m_size / sizeof(wchar_t) - 1; \
                *(Int32*)pUsed = (Cq).m_used / sizeof(wchar_t) - 1; \
            } while (0)

#endif //__cplusplus

#endif //__EZSTRBUF_H__
